﻿using System.Data;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using GameSchoolApplication.Models;
using GameSchoolApplication.ViewModels;
using GameSchoolApplication.Repository;
using System.Collections.Generic;

namespace GameSchoolApplication.Controllers
{ 
	[Authorize]
    public class GameController : Controller
    {
        private GameSchoolWebContext _db = new GameSchoolWebContext();
		private GameRepository _game = new GameRepository();

        // GET: /Game/
        public ViewResult Index()
        {
            return View(_game.GetAllGames());
        }

		/// <summary>
		/// Gets all the theacher games
		/// </summary>
		/// <returns></returns>
        public ActionResult TeacherGames()
        {
            Person teacher = _db.Persons.Where(p => p.UserName == User.Identity.Name).SingleOrDefault();
            return View(_game.GetTeacherGames(teacher));
        }

		/// <summary>
		/// Gets all the current games that the student is assigened to
		/// </summary>
		/// <returns></returns>
		public ActionResult StudentGames()
		{
			Person student = _db.Persons.Where(m => m.UserName == User.Identity.Name).SingleOrDefault();
            ViewBag.Student = student;
			return View(student.OpenEnrollments);
		}

        // GET: /Game/Details/5
        public ViewResult Details(int? id)
        {
  			if(id.HasValue)
  			{
  				var gameFound = _game.GetGameById(id);
				if(gameFound != null)
				{
					return View(gameFound);
				}
  			}
            return View("NotFound");
        }

        // GET: /Game/Create
        [HttpGet]
        public ActionResult Create()
        {
            Person currentUser = _db.Persons.Where(m => m.UserName == User.Identity.Name).SingleOrDefault();
            return View(new Game { AuthorId = currentUser.Id });
        } 

        // POST: /Game/Create
        [HttpPost]
        public ActionResult Create(Game game)
        {
            if (ModelState.IsValid)
            {
                _game.AddGame(game);
                return RedirectToAction("Index");  
            }

            return View(game);
        }
        
        // GET: /Game/Edit/5
        [HttpGet]
        public ActionResult Edit(int id)
        {
            Game game = _db.Games.Find(id);
            return View(game);
        }

        // POST: /Game/Edit/5
        [HttpPost]
        public ActionResult Edit(Game game)
        {
            if (ModelState.IsValid)
            {
                _db.Entry(game).State = EntityState.Modified;
                _db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(game);
        }

        // GET: /Game/Delete/5 
        public ActionResult Delete(int id)
        {
            Game game = _db.Games.Find(id);
            return View(game);
        }

        // POST: /Game/Delete/5
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {            
            Game game = _db.Games.Find(id);
            _db.Games.Remove(game);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

		/// <summary>
		/// Gets the specific game which we can assign a teacher to
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        [HttpGet]
        public ActionResult AddTeacherToGame(int id)
        {
            AddPersonToGameViewModel model = new AddPersonToGameViewModel();
            model.GameId = id;
            model.Person = _db.Persons.Where(p => p.Group == "Teacher");            
            return View(model);
        }

		/// <summary>
		/// Adds a teacher to a game
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
        [HttpPost]
        public ActionResult AddTeacherToGame(AddPersonToGameViewModel model)
        {
            Person teacher = _db.Persons.Where(p => p.Id == model.TeacherId).SingleOrDefault();
            Game game = _game.GetGameById(model.GameId);

            if (ModelState.IsValid)
            {
                var exists =
                    _db.GameInstructors.Where(m => m.TeacherId == teacher.Id && m.GameId == game.GameId).SingleOrDefault();
                if (exists == null)
                {
                    _game.AddTeacherToGame(new GameInstructor(), teacher, game);
                    return RedirectToAction("Details", new { id = game.GameId });
                }
            }
            return View("NotFound");
        }

		/// <summary>
		/// Gets the specific game by id and gets all the students 
		/// that are enrolled in GameSchool
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        [HttpGet]
		public ActionResult AddStudentToGame(int id)
		{
			AddPersonToGameViewModel model = new AddPersonToGameViewModel();
			model.GameId = id;
			model.Person = _db.Persons.Where(p => p.Group == "Student");
			return View(model);
		}

		/// <summary>
		/// Adds a specific student to a game
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
		[HttpPost]
		public ActionResult AddStudentToGame(AddPersonToGameViewModel model)
		{
			Person	student = _db.Persons.Where(m => m.Id == model.StudentId).SingleOrDefault();
			Game game = _game.GetGameById(model.GameId);
 
			if (ModelState.IsValid)
			{
				var exists = 
					_db.StudentPoints.Where(m => m.StudentId == student.Id && m.GameId == game.GameId).SingleOrDefault();
				if (exists == null)
				{
					_game.AddStudentToGame(new StudentPoints(), student, game);
                    return RedirectToAction("Details", new { id = game.GameId });
				}
			}
			return View("NotFound");
		}

		/// <summary>
		/// Removes a teacher from a game
		/// </summary>
		/// <param name="instructorId"></param>
		/// <returns></returns>
        public ActionResult RemoveTeacherFromGame(int instructorId)
        {
            GameInstructor instructor = _game.GetGameInstructor(instructorId);
            _game.RemoveTeacherFromGame(instructor);
            return RedirectToAction("Details", new { id = instructor.GameId });
        }

		/// <summary>
		/// Removes a student from a game
		/// </summary>
		/// <param name="enrollmentId"></param>
		/// <returns></returns>
        public ActionResult RemoveStudentFromGame(int enrollmentId)
        {
            StudentPoints enrollment = _game.GetEnrollment(enrollmentId);
            _game.RemoveStudentFromGame(enrollment);
            return RedirectToAction("Details", new { id = enrollment.GameId });

        }
        
		/// <summary>
		/// Teacher opens a game
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
        [HttpPost]
        public ActionResult OpenGame(int id)
        {
            Game game = _game.GetGameById(id);
            if (!game.IsOpen)
            {
                _game.OpenGame(game);
            }
            return Redirect(Url.RouteUrl(new { controller = "Game", action = "TeacherGames" }) + "#game-" + id);
        }

		/// <summary>
		/// Returns the index of the current level
		/// </summary>
		/// <param name="gameId"></param>
		/// <returns></returns>
		[HttpGet]
        public ActionResult GameLevelIndex(int gameId)
        {
            var game = _game.GetGameById(gameId);
            if (game != null)
            {
                return View(game);
            }
            return View("NotFound");
        }

		/// <summary>
		/// Retrurns the score for the specified user
		/// </summary>
		/// <returns></returns>
		[HttpGet]
        public ActionResult Scores()
        {
            Person teacher = _db.Persons.Where(p => p.UserName == User.Identity.Name).SingleOrDefault();
            return View(teacher.GameInstructors.Where(gi => gi.Game.IsOpen));
        }

		/// <summary>
		/// Retuns if not found 
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		public ActionResult NotFound()
		{
			return View("NotFound");
		}

        protected override void Dispose(bool disposing)
        {
            _db.Dispose();
            base.Dispose(disposing);
        }
    }
}